
import networkx as nx
import numpy as np
import os
import json
import pickle
import matplotlib.pyplot as plt


def draw_event(graph, save_path, with_labels=False):
    """
    可视化event的成员关系和成员反应
        -节点绿色为"yes",红色为"no"
        -节点尺寸表示度的大小:尺寸越大,表明与更多数成员topics相似;反之,越不同与其他成员
        -边的粗细表示边权重
        -with_labels:图中是否显示member_id
    """
    plt.figure(figsize=(10,7))
    pos = nx.circular_layout(graph)

    node_color = []
    for node in graph:
        if(graph.nodes[node]["response"]=="yes"):
            node_color.append('green')
        else:
            node_color.append('red')

    node_degree = [graph.degree(v)+2 for v in graph]
    if(max(node_degree) != 0):
        node_degree = np.array(node_degree) / max(node_degree)

    node_size = node_degree * 1000

    edge_weight = [graph[u][v]['weight'] for u,v in graph.edges()]
    edge_width = (np.array(edge_weight) / max(edge_weight))*5
    nx.draw_networkx(graph, pos, node_color=node_color, node_size=node_size, alpha=0.7, with_labels=with_labels, width=edge_width, edge_color='0.6', cmap=plt.cm.Blues)
    plt.axis('off')
    plt.tight_layout()
    plt.savefig(save_path)

    return True

is_member_list_cached:bool = False
member_list_cache: dict = dict()
is_event_graph_cached: bool = False
event_graph_cache: dict = dict()
is_group_list_cached:bool = False
group_list_cache:dict = dict()

is_member_event_cached = False
member_event_cache:dict = dict()

def make_member_event_cache(all_graphs, member_list, event_list):
    global is_member_event_cached
    global member_event_cache
    is_member_event_cached=True
    event_dict = dict()
    graph_dict = dict()
    # for e in event_list:
    #     event_dict[str(e['id'])]=e
    
    for g in all_graphs:
        graph_dict[g.id]=g
    
    for member in member_list:
        m_id = str(member['id'])
        member_event_cache[m_id]=list()
        # for event in all_graphs:
        #     if event.__contains__(m_id):
        #         member_event_cache[m_id].append(event)
    for e in event_list:
        mr = e['member and response']
        for m_id in mr:
            if member_event_cache.__contains__(m_id) and graph_dict.__contains__(str(e['id'])):
                member_event_cache[m_id].append(graph_dict[str(e['id'])])
    print('make member event cache')


def make_group_list_cache(group_list):
    global is_group_list_cached
    global group_list_cache
    is_group_list_cached=True
    for g in group_list:
        g_id = str(g['id'])
        group_list_cache[g_id]=g
    print('make group cache...')

def make_event_graph_cache(all_graphs):
    global is_event_graph_cached
    global event_graph_cache
    is_event_graph_cached = True
    for e in all_graphs:
        event_graph_cache[e.id]=e
    print('make graph cache...')

def make_member_list_cache(member_list):
    global is_member_list_cached
    global member_list_cache
    is_member_list_cached = True
    for m in member_list:
        m_id = str(m['id'])
        member_list_cache[m_id]=m
    print('make member list cache...')

def close_top_k(all_graphs, member_list, event_id, member_id, k):
    """
    面对同一个event邀请,当前社团内最紧密的k个人的topics和response
    返回的list中紧密关系由强到弱[最紧密,...,最不紧密]
    k:网络中他的邻居不足k个时,设k=neibor_nodes
    """
    event_id = str(event_id)
    member_id = str(member_id)
    
    # for event in all_graphs:
    #     if(event.id==event_id):
    #         cur_event = event
    # neibor_nodes = cur_event[member_id]
    # neibor_num_node = len(neibor_nodes)

    if not is_event_graph_cached:
        make_event_graph_cache(all_graphs)
    if not is_member_list_cached:
        make_member_list_cache(member_list)
    
    if event_graph_cache.__contains__(event_id):
        cur_event = event_graph_cache[event_id]
    else:
        return []

    neibor_nodes = cur_event[member_id]
    neibor_num_node = len(neibor_nodes)

    k = k if(k < neibor_num_node) else neibor_num_node
    sorted_neibor = sorted(neibor_nodes.items(), key = lambda i:i[1]["weight"], reverse=True)

    close_list = []
    for id, _ in sorted_neibor:
        # for member in member_list:
        #         if(member["id"]==id):
        #             cur_topics = member["topics"]
        cur_topics=[]
        if member_list_cache.__contains__(id):
            cur_topics = member_list_cache[id]['topics']
        temp = {
            "id" : id,
            "topics" : cur_topics,
            "response" : cur_event.nodes.data()[id]["response"]
        }
        close_list.append(temp)
        if(len(close_list)==k):
            break

    return close_list

def history_response2(all_graphs, event_list, group_list, member_list, event_id, member_id):
    """
    某member在某event之前的收到的历史邀请情况
    返回他面对这些event时的response,以及这些event的topics,返回的list从时间轴上由过去到现在[最久远,...,最接近]
    """
    event_id = str(event_id)
    member_id = str(member_id)

    # for event in all_graphs:
    #     if(event.id==event_id):
    #         cur_event = event

    if not is_event_graph_cached:
        make_event_graph_cache(all_graphs)
    if not is_group_list_cached:
        make_group_list_cache(group_list)
    if not is_member_event_cached:
        make_member_event_cache(all_graphs, member_list, event_list)
    
    
    if event_graph_cache.__contains__(event_id):
        cur_event = event_graph_cache[event_id]
    else:
        return []

    cur_time = cur_event.time
    history_list = []
    # for event in all_graphs:
    if member_event_cache.__contains__(member_id):
        for event in member_event_cache[member_id]:
            if(event.time<cur_time):
                # for group in group_list:
                #     if(group["id"]==event.group_id):
                #         cur_topics = group["topics"]
                cur_topics=[]
                if group_list_cache.__contains__(event.group_id):
                    cur_topics=group_list_cache[event.group_id]['topics']

                temp = {
                    "id" : event.id,
                    "topics" : cur_topics,
                    "time" : event.time,
                    "response" : event.nodes.data()[member_id]["response"]
                    }
                history_list.append(temp)
    history_list = sorted(history_list, key = lambda i:i["time"])###暂时先这样
            
    return history_list

def history_response(all_graphs, group_list, event_id, member_id):
    """
    某member在某event之前的收到的历史邀请情况
    返回他面对这些event时的response,以及这些event的topics,返回的list从时间轴上由过去到现在[最久远,...,最接近]
    """
    event_id = str(event_id)
    member_id = str(member_id)

    # for event in all_graphs:
    #     if(event.id==event_id):
    #         cur_event = event

    if not is_event_graph_cached:
        make_event_graph_cache(all_graphs)
    if not is_group_list_cached:
        make_group_list_cache(group_list)
    
    
    if event_graph_cache.__contains__(event_id):
        cur_event = event_graph_cache[event_id]
    else:
        return []

    cur_time = cur_event.time
    history_list = []
    for event in all_graphs:
        if(event.__contains__(member_id) and event.time<cur_time):
            # for group in group_list:
            #     if(group["id"]==event.group_id):
            #         cur_topics = group["topics"]
            cur_topics=[]
            if group_list_cache.__contains__(event.group_id):
                cur_topics=group_list_cache[event.group_id]['topics']

            temp = {
                "id" : event.id,
                "topics" : cur_topics,
                "time" : event.time,
                "response" : event.nodes.data()[member_id]["response"]
                }
            history_list.append(temp)
    history_list = sorted(history_list, key = lambda i:i["time"])###暂时先这样
            
    return history_list


def group_evolution(all_graphs, group_id):
    """
    某社团所举办的活动的演化过程
    返回的list从时间轴上由过去到现在[最久远,...,最接近]
    """
    group_id = str(group_id)
    
    evolution_list = []
    for event in all_graphs:
        if(event.group_id==group_id):
            evolution_list.append(event)
    evolution_list = sorted(evolution_list, key = lambda i:i.time)

    return evolution_list